﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Security.Principal;

namespace VTFC
{
    // ----------------------------------------------------------------------------
    /// <summary>
    /// Encapsulate common business methods.
    /// </summary>
    // ----------------------------------------------------------------------------
    public class BaseLogic
    {
        // ----------------------------------------------------------------------------
        /// <summary>
        /// Constructor.
        /// </summary>
        // ----------------------------------------------------------------------------
        static BaseLogic()
        {
        }//ctor

        #region Cryptography

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Encrypt plain data.
        /// </summary>
        /// <param name="plaindata">Plain string.</param>
        /// <returns>Encrypted string.</returns>
        // ----------------------------------------------------------------------------
        public static string EncryptString(string plaindata)
        {
            string securedata = null;
            if (!String.IsNullOrEmpty(plaindata))
            {
                byte[] plain = Encoding.Unicode.GetBytes(plaindata);
                byte[] secure = ProtectedData.Protect(plain, null, DataProtectionScope.CurrentUser);
                securedata = Convert.ToBase64String(secure);
            }
            return securedata;
        }//func EncryptString

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Decrypt secure data.
        /// </summary>
        /// <param name="securedata">Encrypted string.</param>
        /// <returns>Plain string.</returns>
        // ----------------------------------------------------------------------------
        public static string DecryptString(string securedata)
        {
            string plaindata = null;
            if (!String.IsNullOrEmpty(securedata))
            {
                byte[] plain = ProtectedData.Unprotect(Convert.FromBase64String(securedata), null, DataProtectionScope.CurrentUser);
                plaindata = Encoding.Unicode.GetString(plain);
            }
            return plaindata;
        }//func DecryptString

        #endregion

        #region Common

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Get the full version string of current application.
        /// </summary>
        /// <returns>Version string.</returns>
        // ----------------------------------------------------------------------------
        public static string GetAssemblyVersion()
        {
            return Assembly.GetExecutingAssembly().GetName().Version.ToString();
        }//func GetAssemblyVersion

        #endregion

        #region Valaidation

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Validate the name as a filename.
        /// </summary>
        /// <param name="filename">Name of the file.</param>
        /// <returns>Valid?</returns>
        // ----------------------------------------------------------------------------
        public static bool ValidateFileName(string filename)
        {
            return filename.IndexOfAny(Path.GetInvalidFileNameChars()) == -1;
        }//ValidateFileName

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Validate the name as a folder.
        /// </summary>
        /// <param name="foldername">Name of the folder.</param>
        /// <returns>Valid?</returns>
        // ----------------------------------------------------------------------------
        public static bool ValidateFolderName(string foldername)
        {
            return !String.IsNullOrEmpty(foldername);
        }//ValidateFolderName

        #endregion

        #region IO

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Get <see cref="System.IO.FileInfo"/> instance.
        /// </summary>
        /// <param name="filepath">File path.</param>
        /// <returns><see cref="System.IO.FileInfo"/> instance</returns>
        // ----------------------------------------------------------------------------
        public static FileInfo GetFileInfo( string filepath )
        {
            return new FileInfo(filepath);
        }//func GetFileInfo

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Get displayable size.
        /// </summary>
        /// <param name="length">Length of the stream.</param>
        /// <returns>Displayable size.</returns>
        // ----------------------------------------------------------------------------
        public static string GetSizeDisplay(long length)
        {
            string display = "";
            if (length < 1024f)
            {
                display = String.Format(Constant.VTFC_SIZE_DISPLAY_KB, (length / 1024f).ToString("0.00"));
            }
            else
            {
                display = String.Format(Constant.VTFC_SIZE_DISPLAY_MB, ((length / 1024f) / 1024f).ToString("0.00"));
            }
            return display;
        }//func GetSizeDisplay

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Clean the path before overwriting.
        /// </summary>
        /// <param name="documentpath">Document path.</param>
        // ----------------------------------------------------------------------------
        public static void CleanPath(string documentpath)
        {
            if (File.Exists(documentpath))
            {
                File.SetAttributes(documentpath, FileAttributes.Normal);
                try
                {
                    File.Delete(documentpath);
                }
                catch (Exception ex)
                {
                    ShowError(ex);
                }
            }
            else
            {
                string directorypath = Path.GetDirectoryName(documentpath);
                CreateDirectory(directorypath);               
            }
        }//func CleanPath

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Create a directory in local.
        /// </summary>
        /// <param name="directorypath">Directory.</param>
        // ----------------------------------------------------------------------------
        public static void CreateDirectory(string directorypath)
        {
            if (!Directory.Exists(directorypath))
            {
                Directory.CreateDirectory(directorypath);
            }
        }//func CreateDirectory

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Delete a directory in local.
        /// </summary>
        /// <param name="directorypath">Directory.</param>
        // ----------------------------------------------------------------------------
        public static void DeleteDirectory(string directorypath)
        {
            if (Directory.Exists(directorypath))
            {
                PreDeleteDirectory(directorypath);
                Directory.Delete(directorypath, true);
            }
        }//func DeleteDirectory

        private static void PreDeleteDirectory(string directorypath)
        {
            foreach (string filepath in Directory.GetFiles(directorypath))
            {
                SetReadOnly(filepath, false);
            }
            foreach (string subdirpath in Directory.GetDirectories(directorypath))
            {
                PreDeleteDirectory(subdirpath);
            }
        }//func PreDeleteDirectory

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Delete a file in local.
        /// </summary>
        /// <param name="documentpath">File path.</param>
        // ----------------------------------------------------------------------------
        public static void DeleteFile(string documentpath)
        {
            if (File.Exists(documentpath))
            {
                SetReadOnly(documentpath, false);
                File.Delete(documentpath);
            }
        }//func DeleteFile

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Select a foder.
        /// </summary>
        /// <param name="defaultfolder">Default folder path.</param>
        /// <returns>Selected folder path.</returns>
        // ----------------------------------------------------------------------------
        public static string SelectFolder(string defaultfolder)
        {
            string folderpath = null;
            using (FolderBrowserDialog fbd = new FolderBrowserDialog())
            {
                if (!String.IsNullOrEmpty(defaultfolder))
                {
                    fbd.SelectedPath = defaultfolder;
                }
                if (fbd.ShowDialog() == DialogResult.OK)
                {
                    folderpath = fbd.SelectedPath;
                }
            }
            return folderpath;
        }//func SelectFolder

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Open one document from local disc.
        /// </summary>
        /// <param name="defaultfolder">Default folder.</param>
        /// <param name="filter">Document extension filter.</param>
        /// <returns>Document path.</returns>
        // ----------------------------------------------------------------------------
        public static string OpenFile(string defaultfolder, string filter)
        {
            string filepath = null;
            using (OpenFileDialog ofd = new OpenFileDialog())
            {
                ofd.Multiselect = false;
                if (!String.IsNullOrEmpty(filter))
                {
                    ofd.Filter = filter;
                }
                if (!String.IsNullOrEmpty(defaultfolder))
                {
                    ofd.InitialDirectory = defaultfolder;
                }
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    filepath = ofd.FileName;
                }
            }
            return filepath;
        }//func OpenFile

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Open local documents.
        /// </summary>
        /// <param name="defaultfolder">Default folder.</param>
        /// <param name="filter">Document extension filter.</param>
        /// <returns>Document paths</returns>
        // ----------------------------------------------------------------------------
        public static List<string> OpenFiles(string defaultfolder, string filter)
        {
            List<string> filepaths = null;
            using (OpenFileDialog ofd = new OpenFileDialog())
            {
                ofd.Multiselect = true;
                if (!String.IsNullOrEmpty(filter))
                {
                    ofd.Filter = filter;
                }
                if (!String.IsNullOrEmpty(defaultfolder))
                {
                    ofd.InitialDirectory = defaultfolder;
                }
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    filepaths = ofd.FileNames.ToList();
                }
            }
            return filepaths;
        }//func OpenFiles

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Select a path for saving.
        /// </summary>
        /// <param name="defaultfolderpath">Default folder path.</param>
        /// <param name="defaultfilename">Default file name.</param>
        /// <returns>Document paths</returns>
        // ----------------------------------------------------------------------------
        public static string SaveFile(string defaultfolderpath, string defaultfilename)
        {
            string filepath = null;
            using (SaveFileDialog sfd = new SaveFileDialog())
            {
                sfd.Title = Resources.SaveFileDialog_Title;
                if (!String.IsNullOrEmpty(defaultfolderpath))
                {
                    sfd.InitialDirectory = defaultfolderpath;
                }
                if (!String.IsNullOrEmpty(defaultfilename))
                {
                    sfd.FileName = defaultfilename;
                    sfd.Filter = String.Format(Resources.SaveFileDialog_FileFilter, Path.GetExtension(defaultfilename));
                }
                if (sfd.ShowDialog() == DialogResult.OK)
                {
                    filepath = sfd.FileName;
                }
            }
            return filepath;
        }//func SaveFile
                               
        // ----------------------------------------------------------------------------
        /// <summary>
        /// Copy the source document to destination folder.
        /// </summary>
        /// <param name="sourcepath">Source document path.</param>
        /// <param name="destinationfolder">Destination folder path.</param>
        /// <returns>Destination file path.</returns>
        // ----------------------------------------------------------------------------
        public static string CopyFile(string sourcepath, string destinationfolder)
        {
            return CopyFile(sourcepath, destinationfolder, false);
        }//func CopyFile

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Copy the source document to destination folder.
        /// </summary>
        /// <param name="sourcepath">Source document path.</param>
        /// <param name="destinationfolder">Destination folder path.</param>
        /// <param name="overwrite">Overwrite the file if exists?</param>
        /// <returns>Destination file path.</returns>
        // ----------------------------------------------------------------------------
        public static string CopyFile(string sourcepath, string destinationfolder, bool overwrite)
        {
            string destinationpath = Path.Combine(destinationfolder, Path.GetFileName(sourcepath));
            return CopyRenamedFile(sourcepath, destinationpath, overwrite);
        }//func CopyFile

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Copy the source document to destination.
        /// </summary>
        /// <param name="sourcepath">Source file path.</param>
        /// <param name="destinationpath">Destination file path.</param>
        /// <param name="overwrite">Overwrite the file if exists?</param>
        /// <returns></returns>
        // ----------------------------------------------------------------------------
        public static string CopyRenamedFile(string sourcepath, string destinationpath, bool overwrite)
        {
            if (destinationpath != sourcepath)
            {
                CleanPath(destinationpath);
                FileInfo info = new FileInfo(sourcepath);
                info.CopyTo(destinationpath, overwrite);
            }
            return destinationpath;
        }//func CopyRenamedFile

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Rename the document.
        /// </summary>
        /// <param name="sourcefilepath">Source file path.</param>
        /// <param name="targetfilename">New file name.</param>
        /// <returns>New file path.</returns>
        // ----------------------------------------------------------------------------
        public static string RenameFile(string sourcefilepath, string targetfilename)
        {
            string targetfilepath = Path.Combine( Path.GetDirectoryName( sourcefilepath), targetfilename );
            File.Move(sourcefilepath, targetfilepath);
            return targetfilepath;
        }//func RenameFile

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Rename a directory.
        /// </summary>
        /// <param name="sourcedirectorypath">Source directory path.</param>
        /// <param name="targetdirectoryname">New directory name.</param>
        /// <returns>New directory path.</returns>
        // ----------------------------------------------------------------------------
        public static string RenameDirectory(string sourcedirectorypath, string targetdirectoryname)
        {
            string targetdirectorypath = Path.Combine( Directory.GetParent( sourcedirectorypath).FullName, targetdirectoryname);
            Directory.Move(sourcedirectorypath, targetdirectorypath);
            return targetdirectorypath;
        }//func RenameDirectory

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Set the readonly attribute value of the document.
        /// </summary>
        /// <param name="documentpath">File path.</param>
        /// <param name="isreadonly">Readonly value.</param>
        // ----------------------------------------------------------------------------
        public static void SetReadOnly(string documentpath, bool isreadonly)
        {
            FileInfo info = new FileInfo(documentpath);
            info.IsReadOnly = isreadonly;
        }//func SetReadOnly

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Get the readonly attribute value of the document.
        /// </summary>
        /// <param name="documentpath">Document path.</param>
        /// <returns>Readonly?</returns>
        // ----------------------------------------------------------------------------
        public static bool GetReadOnly(string documentpath)
        {
            FileInfo info = new FileInfo(documentpath);
            return info.IsReadOnly;
        }//func GetReadOnly

        #endregion

        #region Process

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Start the file in a process.
        /// </summary>
        /// <param name="filepath">Path of the file.</param>
        // ----------------------------------------------------------------------------
        public static void StartProcess(string filepath)
        {
            Process.Start(filepath);
        }//func StartProcess

        #endregion

        #region Messages

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Show error message in dialog.
        /// </summary>
        /// <param name="message">Message text.</param>
        // ----------------------------------------------------------------------------
        public static void ShowError(string message)
        {
            ShowMessage(message, Constant.VTFC_APPLICATION_SMALL_NAME, MessageBoxIcon.Error, MessageBoxButtons.OK);
        }//func ShowError

        // ----------------------------------------------------------------------------
        /// <summary>
        ///  Show <see cref="System.Exception"/> in dialog.
        /// </summary>
        /// <param name="ex"><see cref="System.Exception"/></param>
        // ----------------------------------------------------------------------------
        public static void ShowError(Exception ex)
        {
            ShowMessage(ex.ToString(), Constant.VTFC_APPLICATION_SMALL_NAME, MessageBoxIcon.Error, MessageBoxButtons.OK);
        }//func ShowError

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Show question in dialog.
        /// </summary>
        /// <param name="message">Question.</param>
        /// <returns>Result.</returns>
        // ----------------------------------------------------------------------------
        public static bool ShowQuerstion(string message)
        {
            return DialogResult.Yes == ShowQuerstion(message, true);
        }//func ShowQuerstion

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Show question in dialog.
        /// </summary>
        /// <param name="message">Question.</param>
        /// <param name="cancancel">Show Cancel button.</param>
        /// <returns>Result.</returns>
        // ----------------------------------------------------------------------------
        public static DialogResult ShowQuerstion(string message, bool cancancel)
        {
            return ShowMessage(message, Constant.VTFC_APPLICATION_SMALL_NAME, MessageBoxIcon.Question, MessageBoxButtons.YesNoCancel);
        }//func ShowQuerstion

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Show question in dialog.
        /// </summary>
        /// <param name="message">Warrning.</param>
        // ----------------------------------------------------------------------------
        public static void ShowWarrning(string message)
        {
            ShowMessage(message, Constant.VTFC_APPLICATION_SMALL_NAME, MessageBoxIcon.Warning, MessageBoxButtons.OK);
        }//func ShowWarrning

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Show information in dialog.
        /// </summary>
        /// <param name="message">Information.</param>
        // ----------------------------------------------------------------------------
        public static void ShowInformation(string message)
        {
            ShowMessage(message, Constant.VTFC_APPLICATION_SMALL_NAME, MessageBoxIcon.Information, MessageBoxButtons.OK);
        }//func ShowInformation

        // ----------------------------------------------------------------------------
        /// <summary>
        /// Show message in dialog.
        /// </summary>
        /// <remarks>
        /// Common method for dialog show.
        /// </remarks>
        /// <param name="message">Message text.</param>
        /// <param name="title">Dialog title</param>
        /// <param name="icon"><see cref="System.Windows.Forms.MessageBoxIcon"/></param>
        /// <param name="buttons"><see cref="System.Windows.Forms.MessageBoxButtons"/></param>
        /// <returns><see cref="System.Windows.Forms.DialogResult"/> result.</returns>
        // ----------------------------------------------------------------------------
        public static DialogResult ShowMessage(string message, string title, MessageBoxIcon icon, MessageBoxButtons buttons)
        {
            return MessageBox.Show(message, title, buttons, icon);
        }//func ShowMessage

        #endregion

    }//class BaseLogic
}//namespace VTFC
